/*
 * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */
package im.composer.media.sound.synth;

import java.io.IOException;
import javax.sound.midi.Instrument;
import javax.sound.midi.MidiChannel;
import javax.sound.midi.Patch;
import javax.sound.midi.Soundbank;
import javax.sound.midi.SoundbankResource;
import javax.sound.midi.VoiceStatus;

/**
 * A abstract class used to simplify creating custom ModelOscillator.
 *
 * @author Karl Helgason
 */
public abstract class ModelAbstractOscillator implements ModelOscillator, ModelOscillatorStream, Soundbank {

	protected float pitch = 6000;
	protected float samplerate;
	protected MidiChannel channel;
	protected VoiceStatus voice;
	protected int noteNumber;
	protected int velocity;
	protected boolean on = false;

	public void init() {
	}

	public void close() throws IOException {
	}

	public void noteOff(int velocity) {
		on = false;
	}

	public void noteOn(MidiChannel channel, VoiceStatus voice, int noteNumber, int velocity) {
		this.channel = channel;
		this.voice = voice;
		this.noteNumber = noteNumber;
		this.velocity = velocity;
		on = true;
	}

	public int read(float[][] buffer, int offset, int len) throws IOException {
		return -1;
	}

	public MidiChannel getChannel() {
		return channel;
	}

	public VoiceStatus getVoice() {
		return voice;
	}

	public int getNoteNumber() {
		return noteNumber;
	}

	public int getVelocity() {
		return velocity;
	}

	public boolean isOn() {
		return on;
	}

	public void setPitch(float pitch) {
		this.pitch = pitch;
	}

	public float getPitch() {
		return pitch;
	}

	public void setSampleRate(float samplerate) {
		this.samplerate = samplerate;
	}

	public float getSampleRate() {
		return samplerate;
	}

	public float getAttenuation() {
		return 0;
	}

	public int getChannels() {
		return 1;
	}

	public String getName() {
		return getClass().getName();
	}

	public Patch getPatch() {
		return new Patch(0, 0);
	}

	public ModelOscillatorStream open(float samplerate) {
		ModelAbstractOscillator oscs;
		try {
			oscs = this.getClass().newInstance();
		} catch (InstantiationException e) {
			throw new IllegalArgumentException(e);
		} catch (IllegalAccessException e) {
			throw new IllegalArgumentException(e);
		}
		oscs.setSampleRate(samplerate);
		oscs.init();
		return oscs;
	}

	public ModelPerformer getPerformer() {
		// Create performer for my custom oscillirator
		ModelPerformer performer = new ModelPerformer();
		performer.getOscillators().add(this);
		return performer;

	}

	public ModelInstrument getInstrument() {
		// Create Instrument object around my performer
		SimpleInstrument ins = new SimpleInstrument();
		ins.setName(getName());
		ins.add(getPerformer());
		ins.setPatch(getPatch());
		return ins;

	}

	public Soundbank getSoundBank() {
		// Create Soundbank object around the instrument
		SimpleSoundbank sbk = new SimpleSoundbank();
		sbk.addInstrument(getInstrument());
		return sbk;
	}

	public String getDescription() {
		return getName();
	}

	public Instrument getInstrument(Patch patch) {
		Instrument ins = getInstrument();
		Patch p = ins.getPatch();
		if (p.getBank() != patch.getBank())
			return null;
		if (p.getProgram() != patch.getProgram())
			return null;
		if (p instanceof ModelPatch && patch instanceof ModelPatch) {
			if (((ModelPatch) p).isPercussion() != ((ModelPatch) patch).isPercussion()) {
				return null;
			}
		}
		return ins;
	}

	public Instrument[] getInstruments() {
		return new Instrument[] { getInstrument() };
	}

	public SoundbankResource[] getResources() {
		return new SoundbankResource[0];
	}

	public String getVendor() {
		return null;
	}

	public String getVersion() {
		return null;
	}
}
